package com.mmg.cosplay.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.dashscope.aigc.multimodalconversation.AudioParameters;
import com.mmg.cosplay.entity.R;
import com.mmg.cosplay.entity.dto.UserMessageDTO;
import com.mmg.cosplay.service.EnhancedChatService;
import com.mmg.cosplay.service.IConversationExportService;
import com.mmg.cosplay.service.VoiceService;
import com.mmg.cosplay.utils.RoleContext;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.util.Map;

@Slf4j
@Tag(name = "聊天接口")
@RequiredArgsConstructor
@RestController
@RequestMapping("/chat")
public class ChatController {

    private final EnhancedChatService enhancedChatService;

    private final VoiceService voiceService;

    private final IConversationExportService conversationExportService;

    /**
     * 接收用户消息，返回AI回复（流式，带知识库检索）
     */
    @Operation(summary = "流式聊天（带知识库检索）")
    @PostMapping(value = "/chat", produces = "text/html;charset=UTF-8")
    public Flux<String> chat(@RequestBody UserMessageDTO userMessageDTO) {
        RoleContext.setCurrentId(Long.parseLong(userMessageDTO.getRoleId()));
        // 使用增强聊天服务（带知识库检索）
        return enhancedChatService.chatWithKnowledge(
                userMessageDTO.getMemoryId(), Long.valueOf(userMessageDTO.getRoleId()),
                userMessageDTO.getMessage()
        );
    }

    /**
     * 普通聊天（不使用知识库）
     */
    @Operation(summary = "流式聊天（不使用知识库）")
    @PostMapping(value = "/chat/simple", produces = "text/html;charset=UTF-8")
    public Flux<String> simpleChat(@RequestBody UserMessageDTO userMessageDTO) {
        RoleContext.setCurrentId(Long.parseLong(userMessageDTO.getRoleId()));
        // 使用普通聊天服务
        return enhancedChatService.chatWithoutKnowledge(
                userMessageDTO.getMemoryId(),
                Long.valueOf(userMessageDTO.getRoleId()),
                userMessageDTO.getMessage()
        );
    }

    /**
     * 语音转文字
     */
    @PostMapping("/voice/speech-to-text")
    @ResponseBody
    @Operation(summary = "语音转文字")
    public ResponseEntity<?> speechToText(@RequestParam("audio") MultipartFile audioFile) {
        try {
            if (audioFile == null || audioFile.isEmpty()) {
                return ResponseEntity.badRequest().body(R.error("音频文件不能为空"));
            }

            String text = voiceService.speechToText(audioFile);
            return R.success(text);
        } catch (Exception e) {
            return R.error("语音转文字失败: " + e.getMessage());
        }
    }

    /**
     * 文字转语音 - 支持自定义音色
     */
    @PostMapping("/voice/text-to-speech")
    @ResponseBody
    @Operation(summary = "文字转语音")
    public ResponseEntity<?> textToSpeech(@RequestBody Map<String, Object> data) {
        try {
            String text = data.get("text").toString();
            String cherry = data.get("voice").toString();
            if (text == null || text.trim().isEmpty()) {
                return R.error("文本内容不能为空");
            }

            byte[] audioBytes;

            // 如果指定了音色且不是默认音色，使用自定义音色方法
            if (cherry != null && !cherry.trim().isEmpty() && !"cherry".equalsIgnoreCase(cherry)) {
                audioBytes = voiceService.textToSpeechWithVoice(text, cherry);
                log.info("使用自定义音色进行语音合成: {}", cherry);
            } else {
                audioBytes = voiceService.textToSpeech(text);
                log.info("使用默认音色进行语音合成");
            }

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("audio/wav"));
            headers.setContentLength(audioBytes.length);
            headers.setContentDispositionFormData("attachment", "speech_" + cherry + ".wav");

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(audioBytes); // 返回音频字节数组

        } catch (Exception e) {
            return R.error("文字转语音失败: " + e.getMessage());
        }
    }

    /**
     * 语音聊天 - 结合语音输入和语音回复
     * 完整流程：语音识别 -> AI对话 -> 语音合成
     */
    @PostMapping("/voice/chat")
    @ResponseBody
    @Operation(summary = "语音聊天")
    public ResponseEntity<?> voiceChat(@RequestParam("audio") MultipartFile audioFile,
                                       @RequestParam("memoryId") Long memoryId,
                                       @RequestParam("roleId") Long roleId,
                                       @RequestParam(value = "timbre", required = false) String timbre) {
        try {
            Long userId = Long.parseLong(StpUtil.getLoginId().toString());
            log.info("开始语音聊天，用户ID: {}, 会话ID: {}", userId, memoryId);

            // 1. 语音转文字 (使用阿里云实时语音识别)
            log.info("步骤1: 开始语音识别");
            String userText = voiceService.speechToText(audioFile);
            log.info("语音识别结果: {}", userText);

            if (userText == null || userText.trim().isEmpty()) {
                return ResponseEntity.badRequest().body(R.error("语音识别失败，请重新录音"));
            }

            // 2. 调用AI智能体进行对话
            log.info("步骤2: 开始AI对话，输入: {}", userText);
            StringBuilder aiResponse = new StringBuilder();
            RoleContext.setCurrentId(roleId);
            // 使用增强聊天服务（带知识库检索）
            enhancedChatService.chatWithoutKnowledge(
                            String.valueOf(memoryId), roleId,
                            userText
                    ).doOnNext(chunk -> {
                        aiResponse.append(chunk);
                        log.debug("AI响应流: {}", chunk);
                    })
                    .doOnComplete(() -> log.info("AI对话完成"))
                    .doOnError(error -> log.error("AI对话错误: {}", error.getMessage()))
                    .blockLast(); // 等待流式响应完成

            String aiText = aiResponse.toString();
            log.info("AI回复: {}", aiText.substring(0, Math.min(100, aiText.length())));

            if (aiText == null || aiText.trim().isEmpty()) {
                return ResponseEntity.badRequest().body(R.error("AI对话失败，请重试"));
            }

            // 3. AI回复转语音 (使用阿里云Qwen-TTS)
            log.info("步骤3: 开始语音合成");
            byte[] aiAudioBytes = voiceService.textToSpeech(aiText);
            String aiAudioBase64 = voiceService.encodeToBase64(aiAudioBytes);
            log.info("语音合成完成，音频大小: {} bytes", aiAudioBytes.length);

            // 5. 构建响应数据
            java.util.Map<String, Object> result = new java.util.HashMap<>();
            result.put("userText", userText);                                        // 用户语音识别的文字
            result.put("aiText", aiText);                                           // AI回复的文字
            result.put("aiAudio", aiAudioBase64);                                   // AI回复的语音(Base64编码)
            result.put("aiAudioMimeType", voiceService.getAudioMimeType("wav"));    // 音频MIME类型
            result.put("success", true);

            return R.success(result);

        } catch (Exception e) {
            return R.error("语音聊天失败: " + e.getMessage());
        }
    }

    /**
     * 导出会话为PDF格式
     */
    @Operation(summary = "导出会话为PDF")
    @GetMapping("/export/pdf/{memoryId}")
    public ResponseEntity<byte[]> exportConversationToPdf(@PathVariable("memoryId") String memoryId) {
        try {
            return conversationExportService.exportToPdf(memoryId);
        } catch (Exception e) {
            log.error("导出PDF失败: memoryId={}", memoryId, e);
            return ResponseEntity.badRequest().build();
        }
    }

    /**
     * 导出会话为Markdown格式
     */
    @Operation(summary = "导出会话为Markdown")
    @GetMapping("/export/markdown/{memoryId}")
    public ResponseEntity<byte[]> exportConversationToMarkdown(@PathVariable("memoryId") String memoryId) {
        try {
            return conversationExportService.exportToMarkdown(memoryId);
        } catch (Exception e) {
            log.error("导出Markdown失败: memoryId={}", memoryId, e);
            return ResponseEntity.badRequest().build();
        }
    }
}
